#!/bin/bash

# ==============================================================================
# Script: switch_aosp_tag.sh
# Description: Switches an AOSP workspace to a specific release tag.
#              It ensures the workspace perfectly matches the target manifest by:
#              1. Downloading newly added repositories.
#              2. Deleting repositories that are no longer in the manifest.
#              3. Checking out the exact git commits specified for all projects.
# Author: dongjinguang
# Version: 2.0
# Use method: ./switch_aosp_tag.sh /path/to/my/aosp android-13.0.0_r45
# ==============================================================================

set -uo pipefail

# --- Configuration & Defaults ---
DEFAULT_AOSP_ROOT="."
DEFAULT_TARGET_TAG="android-14.0.0_r28" # A recent stable tag, change if needed
SYNC_JOBS=${SYNC_JOBS:-16} # Use environment variable or default to 16

# --- Color Definitions ---
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# --- Usage Function ---
usage() {
  cat <<-EOF
Usage: $(basename "$0") [AOSP_ROOT_PATH] [TARGET_TAG]

Synchronizes an AOSP workspace to a specific release tag, ensuring a clean state.

Arguments:
  AOSP_ROOT_PATH  Optional. The path to your AOSP source code root.
                  Defaults to the current directory ("${DEFAULT_AOSP_ROOT}").
  TARGET_TAG      Optional. The specific AOSP release tag to switch to.
                  Defaults to '${DEFAULT_TARGET_TAG}'.

Options:
  -h, --help      Display this help message and exit.

Examples:
  # Switch the current directory to Android 13
  $(basename "$0") . android-13.0.0_r45

  # Switch a specific directory using the default tag
  $(basename "$0") /path/to/my/aosp

  # Use all defaults (run from within the AOSP root)
  $(basename "$0")
EOF
  exit 1
}

# --- Argument Parsing ---
if [[ "${1-}" == "-h" || "${1-}" == "--help" ]]; then
  usage
fi

AOSP_ROOT="${1:-$DEFAULT_AOSP_ROOT}"
TARGET_TAG="${2:-$DEFAULT_TARGET_TAG}"

# --- Initial Validation ---
# Resolve to an absolute path for clarity in messages
AOSP_ROOT=$(cd "$AOSP_ROOT" && pwd)
if [ $? -ne 0 ]; then
  echo -e "${RED}Error: AOSP root directory '$1' not found.${NC}"
  exit 1
fi

if [ ! -d "$AOSP_ROOT/.repo" ]; then
  echo -e "${RED}Error: Directory '$AOSP_ROOT' does not appear to be a valid repo workspace (missing .repo subdirectory).${NC}"
  exit 1
fi

# --- Main Logic ---

# Define a cleanup function and set a trap to run it on exit
TEMP_PROJECT_LIST="$AOSP_ROOT/.repo/project.list"
cleanup() {
  rm -f "$TEMP_PROJECT_LIST"
}
trap cleanup EXIT

echo -e "${BLUE}--- AOSP Tag Switcher ---${NC}"
echo -e "Workspace:    ${YELLOW}${AOSP_ROOT}${NC}"
echo -e "Target Tag:   ${YELLOW}${TARGET_TAG}${NC}"
echo -e "Sync Jobs:    ${YELLOW}${SYNC_JOBS}${NC}"
echo

cd "$AOSP_ROOT" || exit

echo -e "${BLUE}>>> Step 1/4: Re-initializing repo to target tag...${NC}"
repo init -u https://android.googlesource.com/platform/manifest -b "$TARGET_TAG" --depth=1 --no-repo-verify
if [ $? -ne 0 ]; then
  echo -e "${RED}Error: repo init failed. Aborting.${NC}"
  exit 1
fi

echo -e "\n${BLUE}>>> Step 2/4: Syncing all projects to match the new manifest...${NC}"
echo "This may take a while."
repo sync -c -d --prune -j"$SYNC_JOBS"
if [ $? -ne 0 ]; then
  echo -e "${RED}Error: repo sync failed. Aborting.${NC}"
  exit 1
fi

echo -e "\n${BLUE}>>> Step 3/4: Finding obsolete projects for cleanup...${NC}"

# Generate the list of projects required by the new manifest
repo list --path-only > "$TEMP_PROJECT_LIST"

# Find which projects are obsolete
obsolete_projects=()
while IFS= read -r path; do
  obsolete_projects+=("$path")
done < <(repo forall -c 'if ! grep -qxF "$REPO_PATH" ../.repo/project.list; then echo "$REPO_PATH"; fi')

if [ ${#obsolete_projects[@]} -eq 0 ]; then
  echo -e "${GREEN}No obsolete projects found. Workspace is perfectly clean!${NC}"
else
  echo -e "${YELLOW}The following obsolete projects will be deleted:${NC}"
  for proj in "${obsolete_projects[@]}"; do
    echo "  - $proj"
  done
  
  echo
  read -p "Do you want to proceed with deletion? (y/N) " -n 1 -r
  echo
  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "Deletion aborted by user. The workspace is synced but contains extra directories."
    exit 1
  fi

  echo -e "\n${BLUE}>>> Step 4/4: Deleting obsolete projects...${NC}"
  for proj in "${obsolete_projects[@]}"; do
    if [ -d "$proj" ]; then
      echo "Deleting: $proj"
      rm -rf "$proj"
    fi
  done
fi

echo -e "\n${GREEN}✔ Success! Workspace has been switched to ${TARGET_TAG}.${NC}"
echo "Your AOSP tree now precisely matches the manifest for this version."
